#!/usr/bin/env python3
# -*- coding=utf-8 -*-
# 本脚由亁颐堂现任明教教主编写，用于乾颐盾Python课程！
# 教主QQ:605658506
# 亁颐堂官网www.qytang.com
# 教主技术进化论拓展你的技术新边疆
# https://ke.qq.com/course/271956?tuin=24199d8a

from django.shortcuts import render
from datetime import timedelta, timezone
from django.http import HttpResponseRedirect, HttpResponse
from difflib import *
import re
import os
from devnet.models import Department, Navbar, Devicedb, Deviceconfig, DeviceconfigDir
from django.contrib.auth.decorators import permission_required
configdir = DeviceconfigDir.objects.get(id=1).dir_name


@permission_required('devnet.view_deviceconfig')
def device_config(request):  # 设备配置默认页面
    html_title = Department.objects.get(name='admin').departtitle.title
    navbar_list = []
    for navbar in Navbar.objects.all().order_by('id'):
        navbar_list.append([navbar.name, navbar.url])
    active_navbar = '设备配置备份'

    # 从Devicedb数据库表获取所有的设备信息
    all_devices = Devicedb.objects.all()
    devices_list = []
    # 产生包含所有设备名称的列表devices_list
    for x in all_devices:
        devices_list.append({'id': x.id, 'name': x.name})
    try:
        current_device_obj = all_devices[0]
        current = current_device_obj.name  # 由于是设备配置的默认页面,所以我们找到设备清单中的第一个设备
        current_device_id = current_device_obj.id
        # 在Deviceconfig中找到第一个设备的配置信息,按照时间倒序排序
        deviceconfig = Deviceconfig.objects.filter(device=current_device_obj).order_by('-backup_datetime')
        device_config_date_hash = []
        for x in deviceconfig:
            # 读取第一个设备的所有配置备份信息, 制作一个字典, 然后逐个添加到device_config_date_hash列表中
            device_config_date_hash.append({'name': current,  # 设备名称
                                            'hash': x.hash,  # 配置MD5值
                                            'id': x.id,  # 配置唯一ID
                                            # 配置备份时间
                                            'date': x.backup_datetime.strftime('%Y-%m-%d %H:%M'),
                                            # 删除配置链接
                                            'delete_url': '/device_config/delete/' + str(current_device_id) + '/' + str(x.id),
                                            # 查看配置链接
                                            'show_url': '/device_config/show/' + str(current_device_id) + '/' + str(x.id),
                                            # 下载配置链接
                                            'download_url': '/device_config/download/' + str(current_device_id) + '/' + str(+ x.id)})
        # 返回device_config.html页面, 与相应数据
        return render(request, 'device_config.html', locals())

    except Exception:
        # 如果出现问题, 返回device_config.html页面
        return render(request, 'device_config.html')


@permission_required('devnet.view_deviceconfig')
def device_config_dev(request, device_id):  # 特定设备的设备配置页面
    html_title = Department.objects.get(name='admin').departtitle.title
    navbar_list = []
    for navbar in Navbar.objects.all().order_by('id'):
        navbar_list.append([navbar.name, navbar.url])
    active_navbar = '设备配置备份'

    # 从Devicedb数据库表获取所有的设备信息
    all_devices = Devicedb.objects.all()
    devices_list = []
    # 产生包含所有设备名称的列表devices_list
    for x in all_devices:
        devices_list.append({'id': x.id, 'name': x.name})
    try:
        current_device_obj = Devicedb.objects.get(id=device_id)
        current = current_device_obj.name  # 由于是设备配置的默认页面,所以我们找到设备清单中的第一个设备
        current_device_id = current_device_obj.id
        # 在Deviceconfig中找到第一个设备的配置信息,按照时间倒序排序
        deviceconfig = Deviceconfig.objects.filter(device=current_device_obj).order_by('-backup_datetime')
        device_config_date_hash = []
        for x in deviceconfig:
            # 读取第一个设备的所有配置备份信息, 制作一个字典, 然后逐个添加到device_config_date_hash列表中
            device_config_date_hash.append({'name': current,  # 设备名称
                                            'hash': x.hash,  # 配置MD5值
                                            'id': x.id,  # 配置唯一ID
                                            # 配置备份时间
                                            'date': x.backup_datetime.strftime('%Y-%m-%d %H:%M'),
                                            # 删除配置链接
                                            'delete_url': '/device_config/delete/' + str(current_device_id) + '/' + str(
                                                x.id),
                                            # 查看配置链接
                                            'show_url': '/device_config/show/' + str(current_device_id) + '/' + str(
                                                x.id),
                                            # 下载配置链接
                                            'download_url': '/device_config/download/' + str(
                                                current_device_id) + '/' + str(+ x.id)})
        # 返回device_config.html页面, 与相应数据
        return render(request, 'device_config.html', locals())

    except Exception:
        # 如果出现问题, 返回device_config.html页面
        return render(request, 'device_config.html')


@permission_required('devnet.view_deviceconfig')
def device_show_config(request, device_id, id):  # 查看特定设备, 特定ID配置备份页面
    html_title = Department.objects.get(name='admin').departtitle.title
    navbar_list = []
    for navbar in Navbar.objects.all().order_by('id'):
        navbar_list.append([navbar.name, navbar.url])
    active_navbar = '设备配置备份'

    # 从数据库Deviceconfig中获取特定设备,特定ID的配置
    device = Devicedb.objects.get(id=device_id)
    deviceconfig = Deviceconfig.objects.get(device=device, id=id)

    devicename = device.name
    date = deviceconfig.backup_datetime.strftime('%Y-%m-%d %H:%M')
    config = open(configdir + deviceconfig.config_filename, 'r').read()
    # 返回show_config.html页面
    return render(request, 'show_config.html', locals())


@permission_required('devnet.delete_deviceconfig')
def device_del_config(request, device_id, id):  # 删除特定设备, 特定ID配置
    html_title = Department.objects.get(name='admin').departtitle.title
    navbar_list = []
    for navbar in Navbar.objects.all().order_by('id'):
        navbar_list.append([navbar.name, navbar.url])
    active_navbar = '设备配置备份'

    # 从数据库Deviceconfig删除特定设备, 特定ID配置 条目
    device = Devicedb.objects.get(id=device_id)
    deviceconfig = Deviceconfig.objects.get(device=device, id=id)
    deviceconfig.delete()
    os.remove(configdir + deviceconfig.config_filename)

    # 删除后, 重定向到查看特定设备备份配置页面
    return HttpResponseRedirect('/device_config/' + str(device_id))


@permission_required('devnet.view_deviceconfig')
def device_download_config(request, device_id, id):
    # 获取特定设备, 特定ID配置备份
    device = Devicedb.objects.get(id=device_id)
    deviceconfig = Deviceconfig.objects.get(device=device, id=id)

    # 由于下载系统为win!所以需要替换linux的换行符\n到win的换行符'\r\n'
    config_content = open(configdir + deviceconfig.config_filename, 'r').read()
    content = config_content.replace('\n', '\r\n')
    # 配置HTTP响应内容为content(文件内容), content_type='text/plain'
    response = HttpResponse(content, content_type='text/plain')
    # 在'Content-Disposition'中添加文件名
    response['Content-Disposition'] = 'attachment; filename={0}'.format(deviceconfig.config_filename)
    return response


@permission_required('devnet.view_deviceconfig')
def device_config_compare(request, device_id, id1, id2):
    html_title = Department.objects.get(name='admin').departtitle.title
    navbar_list = []
    for navbar in Navbar.objects.all().order_by('id'):
        navbar_list.append([navbar.name, navbar.url])
    active_navbar = '设备配置备份'
    device = Devicedb.objects.get(id=device_id)
    # 获取特定设备的配置1
    deviceconfig1 = Deviceconfig.objects.get(device=device, id=id1)
    # 使用'\r\n'或者'\n'分割设备配置1成为列表, ASA的配置使用'\r\n', 其它使用'\n'
    config1_list = re.split('\r\n|\n', open(configdir + deviceconfig1.config_filename, 'r').read())
    # 获取特定设备的配置2
    deviceconfig2 = Deviceconfig.objects.get(device=device, id=id2)
    # 使用'\r\n'或者'\n'分割设备配置2成为列表, ASA的配置使用'\r\n', 其它使用'\n'
    config2_list = re.split('\r\n|\n', open(configdir + deviceconfig2.config_filename, 'r').read())
    # 使用Python内置的Differ()进行对比, 不用导入模块(这个部分困惑了我一阵子)
    result = Differ().compare(config1_list, config2_list)

    # 把比较的结果恢复到正常的文本
    compare_result = '\r\n'.join(list(result))
    devicename = device.name

    # 返回compare_config.html页面
    return render(request, 'compare_config.html', locals())

